using System;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using Yoozoo.Core.Extensions.Engine;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Yoozoo.Mars.Got;
using Random = UnityEngine.Random;

namespace Yoozoo.Gameplay.City
{
    public class CityRealAiCustomerBus
    {
        // 巴士数量
        public readonly static int k_BusMaxCount = 6;
        // 自动营业可使用巴士数量
        public readonly static int k_AutoCityBusinessMaxCount = 6;
        // 巴士资源路径
        private readonly static Dictionary<CityBusinessType, string> k_BusResourcePaths = new Dictionary<CityBusinessType, string>
        {
            {CityBusinessType.Manual, "Assets/ResourcesAssets/City/AIBus/Prefabs/innercity_ai_bus_init.prefab"},
            {CityBusinessType.Auto, "Assets/ResourcesAssets/City/AIBus/Prefabs/innercity_ai_bus.prefab"},
        };

        private readonly static float k_BusOutCityDuration = 1;
        // 巴士上车点起始index SpecialPointList中从6开始
        private readonly static int k_BusDownPointStartIndex = 6;
        // 巴士上车点列表
        public static List<Vector3> k_BusDownPoints;
        // 小人下车间隔
        private readonly static Vector2 k_CustomerGetOffBus = new Vector2(0.5f, 1.5f);
        // 恢复小人间隔
        private readonly static float k_RestoreCustomerInterval = 0.01f;

        private int _busIndex;
        private Transform _busParent;
        private GameObject _busGameObject;
        private Animator _busAnimator;
        
        // 巴士所属营业类型
        public CityBusinessType BusinessType => _businessType;
        private CityBusinessType _businessType = CityBusinessType.Manual;
        
        // 巴士状态
        public CityRealCustomerBusState BusState => _busState;
        private CityRealCustomerBusState _busState;

        // 巴士Ready状态准备时长
        private float _readyDuration = 0;
        
        // 巴士乘客
        private List<CityRealAiNpcInfo> _roleInfoList;
        // 下车人数
        private List<CityAreaNpcController> _npcCtrls;
        // 上车人数
        private int _onBusRoleCount;
        
        private float _delayActionTimer = -1;
        private Action _delayAction;

        public CityRealAiCustomerBus(int index)
        {
            _busIndex = index;
            _busState = CityRealCustomerBusState.None;
            _npcCtrls = new List<CityAreaNpcController>();
        }

        public void Dispose()
        {
            _busGameObject = null;
            _busState = CityRealCustomerBusState.None;
        }

        public void OnUpdate(float deltaTime)
        {
            // 延迟执行的事件
            if (_delayAction != null)
            {
                _delayActionTimer -= deltaTime;
                if (_delayActionTimer < 0)
                {
                    Action callback = _delayAction;
                    _delayAction = null;
                    callback.Invoke();
                }
            }
            
#if UNITY_EDITOR
            UpdateBusName();
#endif
        }

        public void OnPause(bool isPause)
        {
            if (isPause)
            {
                // 暂停
            }
            else
            {
                // 重新开始
                switch (_busState)
                {
                    case CityRealCustomerBusState.None:
                        {
                        }
                        break;
                    
                    case CityRealCustomerBusState.Parking:  // 停车
                        {
                            // 小人下车
                            LoadBusResource(() =>
                            {
                                _busGameObject.SetActive(true);
                                // _busAnimator.SetTrigger(string.Format(k_BusParkingTriggerName, _busIndex));
                            });
                        }
                        break;
                        
                    case CityRealCustomerBusState.OutCity:
                        {
                            // 隐藏小车
                            RecycleBusResource();
                            ChangeBusToState(CityRealCustomerBusState.None);
                        }
                        break;
                }
            }
        }

        /// <summary>
        /// 初始化下车点
        /// </summary>
        public static void InitBusDownPoints()
        {
            if (k_BusDownPoints == null)
            {
                k_BusDownPoints = new List<Vector3>(k_BusMaxCount);
                var pointRoomCfg = CityRealAiManager.GetInstance().ConfigMgr.GetEventPointRoomCfg(CityRealAiConst.WallId);
                for (int i = 0; i < k_BusMaxCount; ++i)
                {
                    k_BusDownPoints.Add(pointRoomCfg.specialPointPosList[k_BusDownPointStartIndex+i]);
                }
            }
        }
        
        /// <summary>
        /// 巴士准备进城
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="readyDuration"></param>
        public void ReadyIntoCity(Transform parent, CityBusinessType businessType, float readyDuration, List<CityRealAiNpcInfo> roleInfoList)
        {
            _busParent = parent;
            _businessType = businessType;
            _readyDuration = readyDuration;
            _roleInfoList = roleInfoList;
            _npcCtrls.Clear();
            _onBusRoleCount = 0;

            ChangeBusToState(CityRealCustomerBusState.Parking);
        }

        /// <summary>
        /// 巴士处于停车位上 （用于还原恢复内城顾客）
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="businessType"></param>
        /// <param name="roleInfoList"></param>
        public void Parking(Transform parent, CityBusinessType businessType, List<CityRealAiNpcInfo> roleInfoList, bool clearBus = true)
        {
            _busParent = parent;
            _businessType = businessType;
            _readyDuration = 0;
            _roleInfoList = roleInfoList;
            if (clearBus)
            {
                // 删除未上车的小人
                foreach (var npcCtrl in _npcCtrls)
                {
                    // 移除小人
                    npcCtrl.RemoveFromContainer();  // 不是移除所有小人的情况，就需要将小人从Container中移除
                    npcCtrl.Dispose();
                }
                _npcCtrls.Clear();
                _onBusRoleCount = 0;
            }

            LoadBusResource(() =>
            {
                if (!_busGameObject.activeSelf)
                {
                    _busGameObject.SetActive(true);
                }
                // _busAnimator.SetTrigger(string.Format(k_BusParkingTriggerName, _busIndex));
                RestoreCustomerInCity();
            });
            _busState = CityRealCustomerBusState.Parking;
        }

        /// <summary>
        /// npc 跳转到指定房间附近
        /// </summary>
        public void NpcJumpToRoomNearby()
        {
            if (_roleInfoList == null || _roleInfoList.Count <= 0)
            {
                return;
            }

            MoveJumpToRoomNPc();
            CreateJumpToRoomNpc();
            LoadBusResource(() =>
            {
                if (!_busGameObject.activeSelf)
                {
                    _busGameObject.SetActive(true);
                }
                // _busAnimator.SetTrigger(string.Format(k_BusParkingTriggerName, _busIndex));
            });
            _busState = CityRealCustomerBusState.Parking;
        }

        private void MoveJumpToRoomNPc()
        {
            for (int i = 0; i < _npcCtrls.Count; i++)
            {
                var npcCtrl = _npcCtrls[i];
                var roleInfo = _roleInfoList[i];
                CityRealAiAreaManager areaMgr = null;
                var containerMgr = npcCtrl.GetContainerMgr();
                if (containerMgr is CityRealAiWallManager) // 如果在城墙内，则npc需要跳转。
                {
                    areaMgr = CityRealAiManager.GetInstance().GetOrCreateArea(CityRealAiConst.WallAreaId);
                }
                else if (containerMgr is CityRealAiAreaManager)
                {
                    areaMgr = (containerMgr as CityRealAiAreaManager);
                }

                if (areaMgr == null)
                {
                    continue;
                }
                
                npcCtrl.RemoveFromContainer();
                var buildingId = roleInfo.buildingId;
                if (buildingId <= 0)
                {
                    buildingId = CityRealAiConst.HallId;
                }
                var targetRoomMgr = areaMgr.GetRoom(buildingId, 1);
                targetRoomMgr.AddNpcCtrl(npcCtrl);
                var localPos = targetRoomMgr.GetNpcJumpToRoomPos();
                var worldPos = targetRoomMgr.GetWorldPos(localPos);
                if (npcCtrl.IsLoadComplete)
                {
                    npcCtrl.UpdateContainer(targetRoomMgr);
                    npcCtrl.ExecuteNpcJumpToRoom(worldPos);
                }
                else
                {
                    npcCtrl.UpdateBirthPosition(worldPos);
                    npcCtrl.SetupIsJumpToRoomCustomer(true);
                }
            }
        }

        private void CreateJumpToRoomNpc()
        {
            int index = _npcCtrls.Count;
            if (index < _roleInfoList.Count)
            {
                // 清理当前执行事件
                AddDelayAction(0,  null);
                for (int i = index; i < _roleInfoList.Count; i++)
                {
                    var roleInfo = _roleInfoList[i];
                    var areaMgr = CityRealAiManager.GetInstance().GetOrCreateArea(CityRealAiConst.WallAreaId);
                    var buildingId = roleInfo.buildingId;
                    if (buildingId <= 0)
                    {
                        buildingId = CityRealAiConst.HallId;
                    }
                    var targetRoomMgr = areaMgr.GetRoom(buildingId, 1);
					if (targetRoomMgr == null)
                    {
                        continue;
                    }
                    var localPos = targetRoomMgr.GetNpcJumpToRoomPos();
                    var worldPos = targetRoomMgr.GetWorldPos(localPos);
                    var npcCtrl = CityRealAiManager.GetInstance().CreateCustomer(roleInfo, _busIndex, worldPos, _businessType, false, true);
                    _npcCtrls.Add(npcCtrl);
                }
            }
        }

        /// <summary>
        /// 小人返回巴士
        /// </summary>
        /// <param name="npcCtrl"></param>
        public void CustomerBackToBus(CityAreaNpcController npcCtrl)
        {

            _npcCtrls.Remove(npcCtrl);

            // 移除小人
            npcCtrl.RemoveFromContainer();  // 不是移除所有小人的情况，就需要将小人从Container中移除
            npcCtrl.Dispose();
            
            // 检测上车人数
            _onBusRoleCount++;
            if (_onBusRoleCount >= _roleInfoList.Count)
            {
                LeaveCity();
            }
        }

        /// <summary>
        /// 巴士准备离开内城 (开启离开倒计时)
        /// </summary>
        public void ReadyToLeaveCity()
        {
            if (_busState != CityRealCustomerBusState.Parking)
            {
                return;
            }

            // 通知小人尽快回到巴士
            foreach (var npcCtrl in this._npcCtrls)
            {
                npcCtrl.TriggerCustomerBusLeave();
            }
            AddDelayAction(CityRealAiConst.CustomerBusLeaveTime, () =>
            {
                LeaveCity();
            });
        }

        /// <summary>
        /// 巴士离开内城
        /// </summary>
        public void LeaveCity()
        {
            RemoveDelayAction();
            
            // 获取巴士离开cd，防止撞车
            var wallMgr = CityRealAiManager.GetInstance().GetCityRealAiWallManager();
            float delayTime = wallMgr.GetBusLeaveDelayTime();
            AddDelayAction(delayTime, () =>
            {
                // 删除未上车的小人
                foreach (var npcCtrl in _npcCtrls)
                {
                    // 移除小人
                    npcCtrl.RemoveFromContainer();  // 不是移除所有小人的情况，就需要将小人从Container中移除
                    npcCtrl.Dispose();
                }
                _npcCtrls.Clear();
            
                ChangeBusToState(CityRealCustomerBusState.OutCity);
            });
        }

        /// <summary>
        /// 清除巴士
        /// </summary>
        public void ClearBus()
        {
            RemoveDelayAction();
            
            // 删除未上车的小人
            foreach (var npcCtrl in _npcCtrls)
            {
                // 移除小人
                npcCtrl.RemoveFromContainer();  // 不是移除所有小人的情况，就需要将小人从Container中移除
                npcCtrl.Dispose();
            }
            _npcCtrls.Clear();
            
            // 删除巴士
            RecycleBusResource();
            ChangeBusToState(CityRealCustomerBusState.None);
        }
        
        /// <summary>
        /// 销毁所有npc (切出内城时调用)
        /// </summary>
        public void OnResetNpc()
        {
            // 清理小人
            RemoveDelayAction();
            foreach (var npcCtrl in _npcCtrls)
            {
                npcCtrl.Dispose();
            }
            _npcCtrls.Clear();
            // 清理车辆
            RecycleBusResource();
        }

        // 改变巴士状态
        void ChangeBusToState(CityRealCustomerBusState nextState)
        {
            switch (nextState)
            {
                case CityRealCustomerBusState.None:
                    {
                    }
                    break;
                
                case CityRealCustomerBusState.Parking:  // 停车
                    {
                        // 小人下车
                        LoadBusResource(() =>
                        {
                            if (!_busGameObject.activeSelf)
                            {
                                _busGameObject.SetActive(true);
                            }
                            CustomerGetOffBus();
                        });
                    }
                    break;
                    
                case CityRealCustomerBusState.OutCity:
                {
                    LoadBusResource(() =>
                    {
                        AddDelayAction(k_BusOutCityDuration, () =>
                        {
                            // 隐藏小车
                            RecycleBusResource();
                            
                            ChangeBusToState(CityRealCustomerBusState.None);
                        });
                    });
                }
                break;
            }
            
            // 切换状态
            _busState = nextState;
        }

        // 小人下车
        void CustomerGetOffBus()
        {
            int index = _npcCtrls.Count;
            if (index >= _roleInfoList.Count)
            {
                return;
            }

            float delayTime = Random.Range(k_CustomerGetOffBus.x, k_CustomerGetOffBus.y);
            AddDelayAction(delayTime, () =>
            {
                if (index >= _roleInfoList.Count)
                {
                    return;
                }
                
                var roleInfo = _roleInfoList[index];
                // 顾客下车排队
                Vector3 worldPos = _busParent.TransformPoint(k_BusDownPoints[_busIndex - 1]);
                var npcCtrl = CityRealAiManager.GetInstance().CreateCustomer(roleInfo, _busIndex, worldPos, _businessType, false);
                _npcCtrls.Add(npcCtrl);
                
                if (_npcCtrls.Count < _roleInfoList.Count)
                {
                    CustomerGetOffBus();
                }
            });
        }

        // 将小人随机在内城（恢复营业中的状态）
        void RestoreCustomerInCity()
        {
            int index = _npcCtrls.Count;
            if (index >= _roleInfoList.Count)
            {
                return;
            }
            
            AddDelayAction(k_RestoreCustomerInterval, () =>
            {
                if (index >= _roleInfoList.Count)
                {
                    return;
                }
                
                var roleInfo = _roleInfoList[index];
                // 顾客随机到内城中
                Vector3 worldPos = CityRealAiCSharpCallLuaManager.GetAreaRandomPos(CityRealAiConst.WallAreaId);
                var npcCtrl = CityRealAiManager.GetInstance().CreateCustomer(roleInfo, _busIndex, worldPos, _businessType, true);
                _npcCtrls.Add(npcCtrl);
                
                if (_npcCtrls.Count < _roleInfoList.Count)
                {
                    RestoreCustomerInCity();
                }
            });
        }

        void LoadBusResource(Action callback)
        {
            if (!_busGameObject)
            {
                // string busResPath = k_BusResourcePaths[_businessType];
                // CityRealAiManager.GetInstance().Pop(busResPath, go =>
                // {
                //     if (_busGameObject)
                //     {
                //         CityRealAiManager.GetInstance().Push(busResPath, go);
                //         callback.Invoke();
                //         return;
                //     }
                //     
                //     _busGameObject = go;
                //     _busGameObject.SetParent(_busParent);
                //     _busGameObject.transform.localPosition = Vector3.zero;
                //     _busAnimator = _busGameObject.GetComponentInChildren<Animator>();
                //     callback.Invoke();
                // });
                
                _busGameObject = new GameObject();
                _busGameObject.SetParent(_busParent);
                _busGameObject.transform.localPosition = Vector3.zero;
                callback.Invoke();
            }
            else
            {
                callback.Invoke();
            }
        }

        void RecycleBusResource()
        {
            if (_busGameObject)
            {
                // string busResPath = k_BusResourcePaths[_businessType];
                // CityRealAiManager.GetInstance().Push(busResPath, _busGameObject);
                
                GameObject.Destroy(_busGameObject);
            }
            // 重置数据
            _busGameObject = null;
            _busAnimator = null;
            _roleInfoList = null;
            _busState = CityRealCustomerBusState.None;
        }

        void AddDelayAction(float interval, Action callback)
        {
            _delayActionTimer = interval;
            _delayAction = callback;
        }

        void RemoveDelayAction()
        {
            _delayActionTimer = -1;
            _delayAction = null;
        }
        
        public void UpdateBusName()
        {
#if UNITY_EDITOR
            if (_busGameObject)
            {
                if (BusinessType == CityBusinessType.Auto)
                {
                    _busGameObject.name = $"AutoBus({_busIndex}) {_onBusRoleCount}/{_roleInfoList.Count} - {_busState} - {_delayActionTimer}";
                }
                else
                {
                    _busGameObject.name = $"ManualBus({_busIndex}) {_onBusRoleCount}/{_roleInfoList.Count} - {_busState} - {_delayActionTimer}";
                }
            }
#endif
        }
        
    }
}